//
// Created by livio on 2023/3/5.
//

#ifndef CPPDEMO_BASEIOEVENTLOOP_H
#define CPPDEMO_BASEIOEVENTLOOP_H

#include <atomic>

#include "IIOManager.h"
#include "ILoop.h"

class BaseIOEventLoop : public ILoop, public IIOManager {
public:
    BaseIOEventLoop() = default;

    // override from ILoop
    void init() override;

    // override from ILoop
    void run() override;

    // override from ILoop
    void runOnce() override;

    // override from ILoop
    void wakeup() override;

    // override from ILoop
    void close() override;

    // override from ILoop
    void isClosed() override;

    // override from ILoop
    void setBusyLoop(bool on) final;

    // override from IIOManager
    void registerEvent(const IIOObject &object, const IOEvent &event) override;

    // override from IIOManager
    void unregisterEvent(const IIOObject &object) override;

    // override from IIOManager
    void updateEvent(const IIOObject &object, const IOEvent &event) override;

protected:
    enum class Event : uint8_t {
        WAKEUP = 0x01,
        REGISTER,
        UPDATE,
        UNREGISTER,
        CLOSE,
    };

    /**
     * 定义内部事件
     */
    class InternalEvent {
    public:
        explicit InternalEvent(const Event &event) : innerEvent{event} {}

        virtual ~InternalEvent() = default;

        [[nodiscard]] const Event &getEvent() const {
            return innerEvent;
        }

    private:
        const Event innerEvent;
    };

    /**
     * 定义唤醒事件
     */
    class WakeupEvent : InternalEvent {
    public:
        WakeupEvent() : InternalEvent{Event::WAKEUP} {}
    };

    /**
     * 定义关闭事件
     */
    class CloseEvent : InternalEvent {
    public:
        CloseEvent() : InternalEvent{Event::CLOSE} {}
    };

    /**
     * 定义IO事件
     */
    class InternalIOEvent : InternalEvent {
    public:
        explicit InternalIOEvent(const IIOObject &obj, const Event &event)
                : InternalEvent{event}, sockfd{obj.getFileDescriptor()} {}

        [[nodiscard]] const SOCKET &getFileDescriptor() const {
            return sockfd;
        }

    private:
        const SOCKET sockfd{INVALID_SOCKET};
    };

    /**
     * 定义IO注册事件
     */
    class RegisterEvent : InternalIOEvent {
    public:
        explicit RegisterEvent(const IIOObject &obj, const IOEvent &event) :
                InternalIOEvent{obj, Event::REGISTER}, ioEvent{event} {}

        const IOEvent &getIOEvent() const {
            return ioEvent;
        }

    private:
        const IOEvent ioEvent;
    };

    /**
     * 定义IO注销事件
     */
    class UnregisterEvent : InternalIOEvent {
    public:
        explicit UnregisterEvent(const IIOObject &obj) :
                InternalIOEvent{obj, Event::UNREGISTER} {}
    };

    /**
     * 定义IO更新事件
     */
    class UpdateEvent : InternalIOEvent {
    public:
        explicit UpdateEvent(const IIOObject &obj, const IOEvent &event) :
                InternalIOEvent{obj, Event::UPDATE}, ioEvent{event} {}

        const IOEvent &getIOEvent() const {
            return ioEvent;
        }

    private:
        const IOEvent ioEvent;
    };

protected:
    virtual void processEvent() = 0;

    virtual void processInnerEvent(const InternalEvent &event) = 0;

    void onInnerEvent(const InternalEvent &event);

protected:
    std::atomic<bool> useBusyLoop{false};
private:
};


#endif //CPPDEMO_BASEIOEVENTLOOP_H
